package com.studyroom.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.studyroom.dto.Mail;
import com.studyroom.dto.QuestionDTO;
import com.studyroom.dto.Result;
import com.studyroom.dto.UserDTO;
import com.studyroom.entity.Answer;
import com.studyroom.entity.QLike;
import com.studyroom.entity.Question;
import com.studyroom.entity.User;
import com.studyroom.mapper.AnswerMapper;
import com.studyroom.mapper.QLikeMapper;
import com.studyroom.mapper.QuestionMapper;
import com.studyroom.service.MailService;
import com.studyroom.service.QuestionService;
import com.studyroom.service.UserService;
import com.studyroom.utils.DefaultContants;
import com.studyroom.utils.RedisContants;
import com.studyroom.utils.UserHolder;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

import static com.studyroom.utils.DefaultContants.QUESTION_TYPE;
import static com.studyroom.utils.RabbitMqContants.EXCHANGE_TOPIC;

@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private QuestionMapper questionMapper;
    @Resource
    private UserService userService;
    @Resource
    private AnswerMapper answerMapper;
    @Resource
    private QLikeMapper qLikeMapper;
    @Resource
    private MailService mailService;
    @Override
    public Result getListByType(String type) {
        //根据type获取question
        List<Question> questions=null;
        if(type.equals ("全部")){
               questions=questionMapper.selectPage (
                       new Page<Question> (1, DefaultContants.PAGE_SIZE),
                       null).getRecords ();
        }else {
            questions=questionMapper.selectPage (
                    new Page<Question> (1,DefaultContants.PAGE_SIZE),
                    new QueryWrapper<Question> ().eq ("type",type)).getRecords ();
        }
        questions.forEach (question -> {
            this.queryUser (question);
            this.queryLike (question);
            this.queryAnswer (question);
            this.queryPageView(question);
        });
        /*for(QuestionDTO questionDTO:questions){

            QueryWrapper wrapper=new QueryWrapper ();
            wrapper.eq ("question_id",questionDTO.getId ());
            //放入评论数量
            questionDTO.setAnswerCount (answerMapper.selectCount (wrapper));

            //放入点赞数量
            questionDTO.setLikeCount (qLikeMapper.selectCount (wrapper));
        }*/
        return Result.ok (questions);
    }
    private void queryUser(Question question){
        User user=userService.getById (question.getUserId ());
        question.setUsername (user.getUsername ());
        question.setIcon (user.getIcon ());
    }
    private void queryLike(Question question){
        UserDTO userDTO=UserHolder.getUser ();
        String key=RedisContants.LIKE_KEY+question.getId ();
        Long count=stringRedisTemplate.opsForSet ().size (key);
        question.setLiked (count);
        Boolean isMember=stringRedisTemplate.opsForSet ().isMember (key,userDTO.getId ()+"");
        question.setIsLike (BooleanUtil.isTrue (isMember));
    }
    private void queryAnswer(Question question){
        Integer count=answerMapper.selectCount (new QueryWrapper<Answer> ().eq ("question_id",question.getId ()));
        question.setAnswerCount (count.longValue ());
    }
    private void queryPageView(Question question){
        String key=RedisContants.QUESTION_PV_KEY+question.getId ();
        Long pageview = stringRedisTemplate.opsForHyperLogLog ().size (key);
        question.setPageview (pageview);
    }
    @Override
    public Result getListByTitleWithFuzzy(String title) {
        List<QuestionDTO> questions=questionMapper.getListByTitleWithFuzzy (title);
        if(questions.size ()==0){
            return Result.fail ("搜索不到结果");
        }
        for(QuestionDTO questionDTO:questions){

        QueryWrapper wrapper=new QueryWrapper ();
        wrapper.eq ("question_id",questionDTO.getId ());
        //放入评论数量
        questionDTO.setAnswerCount (answerMapper.selectCount (wrapper));

        //放入点赞数量
        questionDTO.setLikeCount (qLikeMapper.selectCount (wrapper));
        }

        return Result.ok (questions);
    }

    @Override
    public Result getAnswersByQuestionId(Long id,Integer current) {
        List<Answer> answers=answerMapper.selectPage (
                new Page<Answer> (current,DefaultContants.PAGE_SIZE),
                new QueryWrapper<Answer> ().eq ("question_id",id)
        ).getRecords ();
        answers.forEach (answer -> {
            User user=userService.getById (answer.getUserId ());
            answer.setUsername (user.getUsername ());
            answer.setIcon (user.getIcon ());
        });
        return Result.ok (answers);
    }

    @Override
    public Result addPageView(Long questionId) {
        String key=RedisContants.QUESTION_PV_KEY+questionId;
        String value=System.currentTimeMillis ()+UserHolder.getUser ().getId ()+"";
        stringRedisTemplate.opsForHyperLogLog ().add (key,value);
        return Result.ok ();
    }

    @Override
    public Result getById(Long id) {
        //从数据库获取question
        Question question=getBaseMapper ().selectById (id);
        //放入用户数据
        this.queryUser (question);
        //放入评论数量和点赞数量
        this.queryLike (question);
        this.queryAnswer (question);
        this.queryPageView (question);
        return Result.ok (question);
    }

    @Override
    public Result add(Question question) {
        UserDTO me= UserHolder.getUser ();
        if(StrUtil.isBlank (question.getType ())){
            question.setType (QUESTION_TYPE);
        }
        question.setUserId (me.getId ());
        question.setCreated (LocalDateTime.now ());
        boolean b=save (question);
        if(!b){
            return Result.fail ("帖子发表失败");
        }
        Mail mail=new Mail ();
        mail.setReceiver (me.getId ());
        mail.setContent ("您的帖子:"+question.getTitle ()+"发表成功了");
        mail.setCreated (LocalDateTime.now ());
        mailService.send (mail);
        return Result.ok ();
    }

    @Override
    public Result del(Long id) {
        /*UserDTO me=UserHolder.getUser ();
        if(!questionDTO.getUserId ().equals (me.getId ())){
            return Result.fail ("你无权删除该帖子");
        }
        boolean b=removeById (questionDTO.getId ());
        if(!b){
            return Result.fail ("删除失败");
        }*/
        return Result.ok ();
    }

    @Override
    public Result getAnswers(Long id) {

        QueryWrapper wrapper=new QueryWrapper ();
        wrapper.eq ("question_id",id);
        List<Answer> answers=answerMapper.selectList (wrapper);

        return Result.ok (answers);
    }

    @Override
    public Result addAnswer(Answer answer) {
        if(answer.getContent ().length ()<2){
            return Result.fail ("评论不能少于2个字");
        }
        UserDTO me=UserHolder.getUser ();
        answer.setCreated (LocalDateTime.now ());
        answer.setUserId ( me.getId ());
        answer.setIcon ( me.getIcon ());
        answer.setUsername ( me.getUsername ());
        int count=answerMapper.insert (answer);
        if(count<0){
            return Result.fail ("回复失败");
        }
        //回复成功，发送mail给目标用户
        User user=userService.getById (answer.getQuestionUserId ());
        mailService.send (new Mail (me.getId (),answer.getQuestionUserId (),user.getUsername ()+"回复了你的问题 '"+answer.getQuestionTitle ()+"'",LocalDateTime.now ()));
        return Result.ok ();
    }

/*    @Override
    public Result clickLike(QuestionDTO questionDTO) {
        UserDTO me=UserHolder.getUser ();
        QueryWrapper wrapper=new QueryWrapper ();
        wrapper.eq ("question_id",questionDTO.getId ());
        wrapper.eq ("user_id",me.getId ());
        QLike qLike=qLikeMapper.selectOne (wrapper);
        if(qLike!=null){
            qLikeMapper.delete (wrapper);
            return Result.ok ();
        }
        int count=qLikeMapper.insert (new QLike (questionDTO.getId (),me.getId ()));
        if(count<0){
            return Result.fail ("点赞失败");
        }
        return Result.ok ();
    }*/
    @Override
    public Result clickLike(Long id){
        UserDTO me=UserHolder.getUser ();
        String key= RedisContants.LIKE_KEY+id;
        Boolean isMember=stringRedisTemplate.opsForSet ().isMember (key,me.getId ()+"");
        if(BooleanUtil.isTrue (isMember)){
            //已存在,取消点赞
            boolean isSuccess=update ().setSql ("liked = liked-1").eq ("id",id).update ();
            if(isSuccess) {
                stringRedisTemplate.opsForSet ().remove (key, me.getId () + "");
            }
        }else{
            //不存在 添加数据
            boolean isSuccess=update ().setSql ("liked = liked+1").eq ("id",id).update ();
            if(isSuccess) {
                stringRedisTemplate.opsForSet ().add (key, me.getId () + "");
            }
        }
        return Result.ok ();
    }
    @Override
    public Result setSolve(Answer answer) {
        UserDTO me=UserHolder.getUser ();
        Question question=getBaseMapper ().selectById (answer.getQuestionId ());
        if(question.getSolveId ()!=null){
            return Result.fail ("该问题已经有最佳答案");
        }
        if(!NumberUtil.equals (me.getId (),question.getUserId ())){
            return Result.fail ("你无权进行此操作");
        }
        question.setSolveId (answer.getId ());
        boolean b=updateById (question);
        if (!b) {
            return Result.fail ("操作失败");
        }
        //mail通知对方的回复被选为最佳答案
        mailService.send (new Mail (me.getId (),answer.getUserId (),"您在’"+answer.getQuestionTitle ()+"‘的回复被选为完美答案",LocalDateTime.now ()));
        return Result.ok ();
    }

}
